﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Speech.Recognition;
using MediaCenterCommander.LocalControl;

namespace MediaCenterCommanderUI
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private string salutation = "telly";
        private SpeechRecognitionEngine srEngine;

        public MainWindow()
        {
            InitializeComponent();
        }

        protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e);

            MediaCenterCommander.LocalControl.MediaCenterLocalController.RegisterStandardChannels();
        }

        private void loadButton_Click_1(object sender, RoutedEventArgs e)
        {            
            if (this.srEngine == null)
            {                
                this.srEngine = new SpeechRecognitionEngine();
                this.srEngine.SetInputToDefaultAudioDevice();

                var builder = new GrammarBuilder();

                if (!String.IsNullOrEmpty(salutation))
                {
                    builder.Append(salutation);
                }

                var choices = new Choices();
                choices.Add("watch c n n");
                choices.Add("watch h g t v");
                choices.Add("watch e s p n");
                choices.Add("watch tennis");
                choices.Add("watch tennis channel");

                choices.Add(this.CreateChannelGrammarBuilder());

                builder.Append(choices);

                var grammar = new Grammar(builder);

                this.srEngine.LoadGrammar(grammar);

                this.srEngine.SpeechRecognized += srEngine_SpeechRecognized;
                this.srEngine.RecognizeAsync(RecognizeMode.Multiple);

                this.recognizedTextBlock.Text = "Started listening...";
            }
        }

        private GrammarBuilder CreateChannelGrammarBuilder()
        {
            var channelBuilder = new GrammarBuilder();
            channelBuilder.Append("channel");

            var channelPartChoices = new Choices();
            channelPartChoices.Add("one");
            channelPartChoices.Add("two");
            channelPartChoices.Add("three");
            channelPartChoices.Add("four");
            channelPartChoices.Add("five");
            channelPartChoices.Add("six");
            channelPartChoices.Add("seven");
            channelPartChoices.Add("eight");
            channelPartChoices.Add("nine");
            channelPartChoices.Add("zero");

            var channelDigitGrammar = new GrammarBuilder(channelPartChoices);
            var channelSpecification = new GrammarBuilder(channelDigitGrammar, 1, 4);

            channelBuilder.Append(channelSpecification);

            return channelBuilder;            
        }
        
        void srEngine_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {
            string text = e.Result.Text + " ---- ";

            foreach (var i in e.Result.Words)
            {
                text += " " + i.Confidence.ToString("0.000");
            }

            this.recognizedTextBlock.Text = text;

            string recognizedText = e.Result.Text;

            bool lackOfConfidenceInSalutation = false;

            if (!String.IsNullOrEmpty(salutation))
            {
                if (recognizedText.StartsWith(salutation))
                {
                    recognizedText = recognizedText.Substring(salutation.Length + 1);
                    if (e.Result.Words[0].Confidence < 0.9)
                    {
                        lackOfConfidenceInSalutation = true;
                    }
                }
            }

            if (!lackOfConfidenceInSalutation)
            {
                if (recognizedText.StartsWith("channel"))
                {
                    this.HandleChannelPhrase(recognizedText);
                }
            }
        }

        private void HandleChannelPhrase(string phrase)
        {
            if (!phrase.StartsWith("channel "))
            {
                return;
            }

            string channelStr = phrase.Substring("channel ".Length).Trim();

            string[] parts = channelStr.Split(' ');

            string numericChannelStr = "";

            foreach (string part in parts)
            {
                switch (part)
                {
                    case "oh":
                    case "zero":
                        numericChannelStr += "0";
                        break;

                    case "one": numericChannelStr += "1"; break;
                    case "two": numericChannelStr += "2"; break;
                    case "three": numericChannelStr += "3"; break;
                    case "four": numericChannelStr += "4"; break;
                    case "five": numericChannelStr += "5"; break;
                    case "six": numericChannelStr += "6"; break;
                    case "seven": numericChannelStr += "7"; break;
                    case "eight": numericChannelStr += "8"; break;
                    case "nine": numericChannelStr += "9"; break;
                }
            }

            numericChannelStr = numericChannelStr.TrimStart('0');

            int channel;

            if (Int32.TryParse(numericChannelStr, out channel))
            {
                try
                {                    
                    MediaCenterLocalController.AttemptToConnectToMediaCenter();
                    MediaCenterLocalController.WatchChannel(channel);
                }
                catch
                {
                    // TODO: report error
                }
            }
        }

        private void tvPowerOn_Click(object sender, RoutedEventArgs e)
        {            
            var tv = TelevisionLocalController.GetTelevisionController(null);

            try
            {
                tv.PowerOn();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void tvPowerOff_Click(object sender, RoutedEventArgs e)
        {
            var tv = TelevisionLocalController.GetTelevisionController(null);

            try
            {
                tv.PowerOff();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void volumeUp_Click(object sender, RoutedEventArgs e)
        {
            var tv = TelevisionLocalController.GetTelevisionController(null);

            try
            {
                tv.VolumeUp();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void volumeDown_Click(object sender, RoutedEventArgs e)
        {
            var tv = TelevisionLocalController.GetTelevisionController(null);

            try
            {
                tv.VolumeDown();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void volumeStatus_Click(object sender, RoutedEventArgs e)
        {
            var tv = TelevisionLocalController.GetTelevisionController(null);

            try
            {
                int volumeLevel = tv.VolumeLevel;
                this.recognizedTextBlock.Text = "Volume = " + volumeLevel;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void tvPowerStatus_Click(object sender, RoutedEventArgs e)
        {
            var tv = TelevisionLocalController.GetTelevisionController(null);

            try
            {
                bool status = tv.IsPoweredOn;
                this.recognizedTextBlock.Text = "Power = " + status;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
    }
}
